package com.mdp.tpa.wechat;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mdp.core.utils.XmlUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mdp.core.err.BizException;

 
public class HttpRequestUtil  {

	static String  contentType="application/json;charset=utf-8";

	private static  Logger log=LoggerFactory.getLogger(HttpRequestUtil.class);
	static ObjectMapper objectMapper=new ObjectMapper() ;
	
	public static Map<String,Object> sendGetXml(String url,  Object param){
		return send(url,"get","xml","utf-8","utf-8",param);
	}
	public static Map<String,Object> sendPostXml(String url, Object param){
		return send(url,"post","xml","utf-8","utf-8",param);
	}
	public static Map<String,Object> sendGetJson(String url, Object param){
		return send(url,"get","json","utf-8","utf-8",param);
	}
	public static Map<String,Object> sendPostJson(String url,  Object param){
		return send(url,"post","json","utf-8","utf-8",param);
	}
	
	public static Map<String,Object> send(String url,String httpMethod,String msgType,String charset,String farCharset, Object param) {
		 
 		CloseableHttpClient httpclient = HttpClients.createDefault();
	    Map<String, Object> responseBody=null;
        try { 
    		log.debug("后端通讯请求 RequestURL："+url);    
    		// Create a custom response handler
            ResponseHandler<Map<String, Object>> responseHandler = new ResponseHandler<Map<String, Object>>() {
 
				@Override
                public Map<String, Object> handleResponse(
                        final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    Map<String,Object> resultMap=new HashMap<String,Object>();
                    String mefarCharset=farCharset;
                    if (status >= 200 && status < 300) { 
                        HttpEntity entity = response.getEntity();
                        mefarCharset=guessCharset(response,mefarCharset);
                        String responeBody=entity != null ? EntityUtils.toString(entity,mefarCharset) : null;
                        log.debug("后端通讯返回数据 responeBody ："+responeBody); 
                        if("xml".equalsIgnoreCase(msgType)){
                        	try {
                        		resultMap= XmlUtils.string2Map(responeBody);
							} catch (Exception e) {
								log.error("",e);
								throw new BizException("HttpProtocol85","将后端通讯返回数据转换成map错误");
							}
                        }else if("json".equalsIgnoreCase(msgType)){
                        	resultMap=objectMapper.readValue(responeBody, HashMap.class);
                        }else if("string".equalsIgnoreCase(msgType)){
                        	resultMap.put("result", responeBody);
                        }
                          
                    } else {
                        throw new ClientProtocolException("Unexpected response status: " + status);
                    }
					return resultMap;
                }

            };
            
        	if("get".equalsIgnoreCase(httpMethod)){
                HttpGet httpget = new HttpGet(url);
                responseBody = httpclient.execute(httpget, responseHandler);
        	}else if("post".equalsIgnoreCase(httpMethod)){
        		
        		HttpPost httpPost = new HttpPost(url); 
                	Object msgBody=param;
                	String sendBody="";
                	if("json".equalsIgnoreCase(msgType) && param==null) {
                		httpPost.addHeader("Content-type","application/json; charset="+farCharset);  
                		httpPost.setHeader("Accept", "application/json");  
                	} else if("json".equalsIgnoreCase(msgType) && ( msgBody instanceof Map ||  msgBody instanceof List)){
                		sendBody=objectMapper.writeValueAsString(msgBody);
                		sendBody=charsetString(sendBody,charset,farCharset);
                		httpPost.addHeader("Content-type","application/json; charset="+farCharset);  
                		httpPost.setHeader("Accept", "application/json");  
                		httpPost.setEntity(new StringEntity(sendBody, Charset.forName(farCharset)));  
                	}else if("json".equalsIgnoreCase(msgType) && msgBody instanceof String){
						sendBody=(String)msgBody;
                 		sendBody=charsetString(sendBody,charset,farCharset);
                		httpPost.addHeader("Content-type","application/json; charset="+farCharset);  
                		httpPost.setHeader("Accept", "application/json");  
                		httpPost.setEntity(new StringEntity(sendBody, Charset.forName(farCharset)));  
                	}else if("xml".equalsIgnoreCase(msgType) && msgBody instanceof String){
                	    sendBody=(String)msgBody;
                	    sendBody=charsetString(sendBody,charset,farCharset);
                		httpPost.setEntity(new StringEntity(sendBody, Charset.forName(farCharset))); 
                	}else if("URL".equalsIgnoreCase(msgType) && msgBody instanceof String) {
                		sendBody=(String)msgBody;
                		sendBody=charsetString(sendBody,charset,farCharset);
                		httpPost.setEntity(new StringEntity(sendBody, Charset.forName(farCharset))); 
                	}else if(msgBody instanceof String){
                		sendBody=(String)msgBody;
                		sendBody=charsetString(sendBody,charset,farCharset);
                		httpPost.setEntity(new StringEntity(sendBody, Charset.forName(farCharset)));
                	}else{
                		throw new BizException("HttpProducer118","未定义的发送数据的格式");
                	}
                	 log.debug("后端通讯发送数据sendBody:"+sendBody); 
                responseBody=httpclient.execute(httpPost,responseHandler);  
        	}
        	
            
            
            
            
        } catch (ClientProtocolException e) {
			throw new BizException(e.getMessage());
		} catch (IOException e) {
			throw new BizException(e.getMessage());
		} finally {
            try {
				httpclient.close();
			} catch (IOException e) {
				throw new BizException(e.getMessage());
			}
        };
		return responseBody;
	}
	
	/**
	 * 字符集转换
	 * @param str
	 * @param fromCharset
	 * @param toCharset
	 * @return
	 */
	public static String charsetString(String str,String fromCharset,String toCharset){
		if(str==null){
			return null;
		}
		if(fromCharset!=null && fromCharset.equalsIgnoreCase(toCharset)){
			return str;
		}else if(fromCharset!=null && toCharset!=null){
			try {
				return new String(str.getBytes(fromCharset),toCharset);
			} catch (UnsupportedEncodingException e) {
				 log.error("",e);
				 return str;
			}
		}else if(fromCharset==null && toCharset!=null){
			try {
				str=new String(str.getBytes(),toCharset);
				return str;
			} catch (UnsupportedEncodingException e) {
				 log.error("",e);
				 return str;
			}
		}else if(fromCharset!=null && toCharset==null){
			try {
				str=new String(str.getBytes(fromCharset));
			} catch (UnsupportedEncodingException e) {
				 log.error("",e);
				 return str;
			}
		}
		return str;
	}
	
	/**
	 * 从header中检测返回数据的编码集合
	 * @param response
	 * @param defaultCharset
	 * @return
	 */
	public static String guessCharset(HttpResponse response,String defaultCharset){
		String mefarCharset=defaultCharset;
		Header contentType=response.getLastHeader("Content-Type");
        String contentTypeValue=contentType.getValue();
         int start=contentTypeValue.indexOf("charset=");
         if(start<0){
         	start=contentTypeValue.indexOf("encoding=");
         	if(start>0){
         		start=start+9;
         	} 
         }else{
         	start=start+8;
         }
         if(start>0){
         	mefarCharset=contentTypeValue.substring(start);
         }
         return mefarCharset;
	}
	
}